package com.szh.library.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.szh.common.enums.ResultCodeEnum;
import com.szh.common.enums.SexEnum;
import com.szh.common.exception.ServiceLibraryException;
import com.szh.common.result.Result;
import com.szh.library.user.client.BookFeignClient;
import com.szh.library.user.mapper.UserMapper;
import com.szh.library.user.service.UserService;
import com.szh.model.Book;
import com.szh.model.User;
import com.szh.vo.BookFindVo;
import com.szh.vo.UserInsertVo;
import com.szh.vo.UserModifyVo;
import com.szh.vo.UserSelectVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: SongZiHao
 * @date: 2023/5/10
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private BookFeignClient bookFeignClient;

    /**
     * 根据id查询用户
     * @param id 用户id
     * @return User
     */
    @Override
    public User selectUserById(Long id) {
        LOGGER.info("selectUserById start....");
        LOGGER.info("待查询用户id ===> {}", id);
        User user = baseMapper.selectById(id);
        if (null == user) {
            LOGGER.error("根据此 id ===> {} 查询的用户信息为空....", id);
            throw new ServiceLibraryException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        LOGGER.info("根据此 id ===> {} 查询的用户信息 ===> {}", id, JSON.toJSONString(user));
        return user;
    }

    /**
     * 查询所有用户
     * @return List<User>
     */
    @Override
    public List<User> selectAllUsers() {
        LOGGER.info("selectAllUsers start....");
        List<User> userList = baseMapper.selectList(null);
        LOGGER.info("查询到的用户列表 ===> {}", JSON.toJSONString(userList));
        return userList;
    }

    /**
     * 条件查询用户，带分页
     * @param page 页码
     * @param limit 每页记录数
     * @param userSelectVo 查询条件vo类
     * @return Page<User>
     */
    @Override
    public Page<User> selectUsersByConditionPage(Long page, Long limit, UserSelectVo userSelectVo) {
        LOGGER.info("selectUsersByConditionPage start....");
        LOGGER.info("selectUsersByConditionPage接口入参 ===> page页码：{}", page);
        LOGGER.info("selectUsersByConditionPage接口入参 ===> limit每页记录数：{}", limit);
        LOGGER.info("selectUsersByConditionPage接口入参 ===> 查询条件：{}", userSelectVo);
        String name = userSelectVo.getName();
        Integer sex = userSelectVo.getSex();
        String address = userSelectVo.getAddress();
        Date createTimeBegin = userSelectVo.getCreateTimeBegin();
        Date createTimeEnd = userSelectVo.getCreateTimeEnd();
        Page<User> pageParam = new Page<>(page, limit);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(name)) {
            queryWrapper.like("name", name);
        }
        if (!StringUtils.isEmpty(sex) && sex > 0) {
            queryWrapper.eq("sex", sex);
        }
        if (!StringUtils.isEmpty(address)) {
            queryWrapper.like("address", address);
        }
        if (!StringUtils.isEmpty(createTimeBegin)) {
            queryWrapper.ge("create_time", createTimeBegin);
        }
        if (!StringUtils.isEmpty(createTimeEnd)) {
            queryWrapper.le("create_time", createTimeEnd);
        }
        Page<User> pageModel = baseMapper.selectPage(pageParam, queryWrapper);
        List<User> users = pageModel.getRecords();
        if (CollectionUtils.isEmpty(users)) {
            LOGGER.error("根据此条件查询的用户列表为空 ===> {}", JSON.toJSONString(userSelectVo));
            return new Page<>();
        }
        LOGGER.info("根据此条件查询的用户总数 ===> {}", pageModel.getTotal());
        LOGGER.info("根据此条件查询的用户列表 ===> {}", JSON.toJSONString(users));
        return pageModel;
    }

    /**
     * 新增用户
     * @param userInsertVo 用户新增vo类
     * @return 是否新增成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    public boolean insertUser(UserInsertVo userInsertVo) {
        LOGGER.info("insertUser start....");
        LOGGER.info("新增用户的部分信息 ===> {}", JSON.toJSONString(userInsertVo));
        String name = userInsertVo.getName();
        Integer age = userInsertVo.getAge();
        Integer sex = userInsertVo.getSex();
        String borrowBooks = userInsertVo.getBorrowBooks();
        String address = userInsertVo.getAddress();
        if (StringUtils.isEmpty(name) || age <= 0 || (!sex.equals(SexEnum.MAN.getSexId()) && !sex.equals(SexEnum.WOMAN.getSexId()))
            || StringUtils.isEmpty(borrowBooks) || StringUtils.isEmpty(address)) {
            LOGGER.error("新增用户的信息中存在非法数据 ===> {}", JSON.toJSONString(userInsertVo));
            throw new ServiceLibraryException(ResultCodeEnum.ILLEGAL_PARAM.getCode(),
                    ResultCodeEnum.ILLEGAL_PARAM.getMessage());
        }
        List<User> users = baseMapper.selectList(null);
        List<String> nameList = users.stream().map(User::getName).collect(Collectors.toList());
        if (nameList.contains(name)) {
            LOGGER.error("此 name ===> {} 已存在于数据库中，请修改姓名之后再次尝试插入!", name);
            throw new ServiceLibraryException(ResultCodeEnum.RECORD_ALREADY_EXISTS.getCode(),
                    ResultCodeEnum.RECORD_ALREADY_EXISTS.getMessage());
        }
        User user = new User();
        user.setName(name);
        user.setAge(age);
        user.setSex(sex.equals(SexEnum.MAN.getSexId()) ? 1 : 2);
        user.setBorrowBooks(borrowBooks);
        user.setAddress(address);
        user.setCreateTime(new Date());
        int row = baseMapper.insert(user);
        if (row == 0) {
            LOGGER.error("新增异常....");
            return false;
        } else {
            LOGGER.info("新增成功 ===> {}", JSON.toJSONString(user));
            return true;
        }
    }

    /**
     * 根据id修改用户
     * @param userModifyVo 用户修改vo类
     * @return 是否修改成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    public boolean modifyUser(UserModifyVo userModifyVo) {
        LOGGER.info("modifyUser start....");
        LOGGER.info("待修改用户的部分信息 ===> {}", JSON.toJSONString(userModifyVo));
        this.selectUserById(userModifyVo.getId()); //修改之前先查一下有没有这条记录，没有了话直接抛异常返回
        User user = new User();
        BeanUtils.copyProperties(userModifyVo, user);
        if (StringUtils.isEmpty(user.getName()) || user.getAge() <= 0
            || StringUtils.isEmpty(user.getBorrowBooks()) || StringUtils.isEmpty(user.getAddress())
            || (!user.getSex().equals(SexEnum.MAN.getSexId()) && !user.getSex().equals(SexEnum.WOMAN.getSexId()))) {
            LOGGER.error("修改之后的用户部分信息不合法，请更正一下再次提交 ===> {}", JSON.toJSONString(user));
            throw new ServiceLibraryException(ResultCodeEnum.ILLEGAL_PARAM.getCode(),
                    ResultCodeEnum.ILLEGAL_PARAM.getMessage());
        }
        user.setUpdateTime(new Date());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", user.getId());
        int row = baseMapper.update(user, queryWrapper);
        if (row == 0) {
            LOGGER.error("修改异常....");
            throw new ServiceLibraryException(ResultCodeEnum.UPDATE_FAILED.getCode(),
                    ResultCodeEnum.UPDATE_FAILED.getMessage());
        } else {
            LOGGER.info("修改成功!!!");
            return true;
        }
    }

    /**
     * 根据id删除用户
     * @param id 用户id
     * @return 是否删除成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    public boolean removeUserById(Long id) {
        LOGGER.info("removeUserById start....");
        LOGGER.info("待删除用户id ===> {}", id);
        User user = this.selectUserById(id); //删除之前先查一下有没有这条记录，没有了话直接抛异常返回
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        int row = baseMapper.delete(queryWrapper);
        if (row == 0) {
            LOGGER.error("根据此 id ===> {} 删除用户失败", id);
            throw new ServiceLibraryException(ResultCodeEnum.DELETE_FAILED.getCode(),
                    ResultCodeEnum.DELETE_FAILED.getMessage());
        } else {
            LOGGER.info("根据此 id ===> {} 删除用户成功，所删用户信息 ===> {}", id, JSON.toJSONString(user));
            return true;
        }
    }

    /**
     * 批量删除用户
     * @param userIds 待删用户id集合
     * @return 是否批量删除成功
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
    public boolean removeBatchByIds(List<Long> userIds) {
        LOGGER.info("removeBatchByIds start....");
        LOGGER.info("待删用户id集合 ===> {}", JSON.toJSONString(userIds));
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", userIds);
        int row = baseMapper.deleteBatchIds(userIds);
        if (row == userIds.size()) {
            LOGGER.info("批量删除成功!!!");
            return true;
        } else {
            LOGGER.error("批量删除异常....");
            throw new ServiceLibraryException(ResultCodeEnum.DELETE_FAILED.getCode(),
                    ResultCodeEnum.DELETE_FAILED.getMessage());
        }
    }

    /**
     * 远程接口调用：根据id查询图书
     * @param id 图书id
     * @return Book
     */
    @Override
    public Book openFeignFindBookById(Long id) {
        LOGGER.info("openFeignFindBookById start....");
        LOGGER.info("待查询图书id ===> {}", id);
        Result<Book> result = bookFeignClient.findBookById(id);
        Book book = result.getData();
        if (null == book) {
            LOGGER.error("根据此 id ===> {} 远程查询的图书信息为空....", id);
            throw new ServiceLibraryException(ResultCodeEnum.QUERY_ONE_NOT_FOUND.getCode(),
                    ResultCodeEnum.QUERY_ONE_NOT_FOUND.getMessage());
        }
        LOGGER.info("根据此 id ===> {} 远程查询的图书信息 ===> {}", id, JSON.toJSONString(book));
        return book;
    }

    /**
     * 远程接口调用：查询所有图书
     * @return List<Book> 图书列表
     */
    @Override
    public List<Book> openFeignFindAllBooks() {
        LOGGER.info("openFeignFindAllBooks start....");
        Result<List<Book>> result = bookFeignClient.findAllBooks();
        List<Book> books = result.getData();
        LOGGER.info("远程查询到的图书列表 ===> {}", JSON.toJSONString(books));
        return books;
    }

    /**
     * 远程接口调用：条件查询图书，带分页
     * @param page 页码
     * @param limit 每页记录数
     * @param bookFindVo 查询条件
     * @return Page<Book>
     */
    @Override
    public Page<Book> openFeignFindBooksByConditionPage(Long page, Long limit, BookFindVo bookFindVo) {
        LOGGER.info("openFeignFindBooksByConditionPage start....");
        Result<Page<Book>> result = bookFeignClient.findBooksByConditionPage(page, limit, bookFindVo);
        Page<Book> pageModel = result.getData();
        List<Book> books = pageModel.getRecords();
        if (CollectionUtils.isEmpty(books)) {
            LOGGER.error("根据此条件查询的图书列表为空 ===> {}", JSON.toJSONString(bookFindVo));
            return new Page<>(page, limit);
        }
        LOGGER.info("根据此条件远程查询的图书总数 ===> {}", pageModel.getTotal());
        LOGGER.info("根据此条件远程查询的图书列表 ===> {}", JSON.toJSONString(books));
        return pageModel;
    }
}
